/* 颜色：格式转换（对 color-convert 的补充）
 * 此处不添加 color-convert 已经支持的，所以应该优先使用 color-convert
 *
 * color-convert 支持的格式：rgb, hsl, hsv, hwb, cmyk, hex, keyword, apple, gray
 *  不支持：oklch, lab
 *  见：https://github.com/Qix-/color-convert?tab=readme-ov-file#color-space-scales
 *
 * 名称
 *  - HexNum: 0xffffff
 *  - HexCss: "#ff0000"
 *  - RgbNorm: [1.0, 1.0, 1.0] // 保留 5 位小数
 *  - Rgb8: [255, 255, 255]
 *  - CssRgb: "rgb(255, 255, 255)"
 *  - Rgb10: [1023, 1023, 1023]
 *  - Rgb12: [4095, 4095, 4095]
 *  - Rgb14: [16383, 16383, 16383]
 *  - Rgb16: [65535, 65535, 65535]
 */
function r5(n: number) {
  return Math.round(n * 100000) / 100000;
}

// MARK: HexNum -----------------------------------------------------------------------------------

/**
 * HexNum 转CSS颜色
 * @param hex 原始值
 * @returns 转换值
 */
function hexNumToCssHex(hex: number) {
  const r = Math.floor(hex / 256 / 256) % 256;
  const g = Math.floor(hex / 256) % 256;
  const b = hex % 256;
  const rs = r.toString(16).padStart(2, "0");
  const gs = g.toString(16).padStart(2, "0");
  const bs = b.toString(16).padStart(2, "0");
  return `#${rs}${gs}${bs}`;
}

/**
 * RGB 转 HexNum
 * @param hex 原始值
 * @returns 转换值
 */
function rgbToHexNum(r: number, g: number, b: number) {
  return r * 256 * 256 + g * 256 + b;
}

/**
 * HexNum 转 RGB
 * @param hex 原始值
 * @returns 转换值
 */
function hexNumToRgb(hex: number) {
  const b = hex % 256;
  hex = Math.floor(hex / 256);
  const g = hex % 256;
  hex = Math.floor(hex / 256);
  const r = hex % 256;
  return [r, g, b];
}

/**
 * NormRGB 转 HexNum
 * @param hex 原始值
 * @returns 转换值
 */
function normRgbToHexNum(rgb: [number, number, number]) {
  let [r, g, b] = rgb;
  r = Math.floor(r * 255);
  g = Math.floor(g * 255);
  b = Math.floor(b * 255);
  return rgbToHexNum(r, g, b);
}

/**
 * HexNum 转 NormRGB
 * @param hex 原始值
 * @returns 转换值
 */
function hexNumToNormRgb(hex: number) {
  const b = hex % 256;
  hex = Math.floor(hex / 256);
  const g = hex % 256;
  hex = Math.floor(hex / 256);
  const r = hex % 256;
  return [r / 255, g / 255, b / 255];
}

// MARK: HexNum -----------------------------------------------------------------------------------

/**
 * 将颜色值 [0-1, 0-1, 0-1] 转为 [255, 255, 255]
 * @param v 原始值
 * @returns 转换值
 */
function rgbNormToCssRgb(v: [number, number, number]) {
  return `rgb(${Math.round(v[0] * 255)}, ${Math.round(
    v[1] * 255
  )}, ${Math.round(v[2] * 255)})`;
}

/**
 * 将颜色值[255, 255, 255] 转为 [0-1, 0-1, 0-1]
 *
 * 保留有效数字是为了让它看起来别那么长；取 5 位是因为这已经足够精确到 16bit 色了。
 * @param rgb255 原始值，范围为 0-255
 * @returns 归一化RGB颜色值
 */
function rgb8ToRgbNorm(
  rgb255: [number, number, number]
): [number, number, number] {
  const [r, g, b] = rgb255;
  return [r5(r / 255), r5(g / 255), r5(b / 255)];
}

// MARK: 导出 -------------------------------------------------------------------------------------

export const color = {
  hexNumToCssHex,
  rgbToHexNum,
  hexNumToRgb,
  normRgbToHexNum,
  hexNumToNormRgb,
  rgbNormToCssRgb,
  rgb8ToRgbNorm,
};
